#include "rtppacket.h"
#include "../Util/debug.h"
#include <stdio.h>
#include <string.h>

RtpPacket::RtpPacket(unsigned char* data, size_t datalen)
{
	DBGPRINT("Info--Get in RtpPacket::RtpPacket(%d, %d)\n", data, datalen);
	m_Packet = new unsigned char[datalen];
	memcpy(m_Packet, data, datalen);
	m_IsBuffered = true;
	DBGPRINT("Info--Get out of RtpPacket::RtpPacket()\n");
}

RtpPacket::RtpPacket(RtpPacket &rtppacket)
{
	DBGPRINT("Info--Get in RtpPacket::RtpPacket(RtpPacket &)\n");
	m_Packet = new unsigned char[rtppacket.GetPacketLen()];
	memcpy(m_Packet, rtppacket.GetPacket(), rtppacket.GetPacketLen());
	m_IsBuffered = true;
	DBGPRINT("Info--Get outof RtpPacket::RtpPacket(RtpPacket &)\n");
}

RtpPacket::~RtpPacket()
{
	if (m_Packet)
	{
		delete[] m_Packet;
		m_Packet = 0;
	}
}

//void RtpPacket::ParsePacket()
//{
//	//V BIT0-1
//	unsigned int aDWord = *((unsigned int *)m_Packet);
//	m_Version = (unsigned char)(aDWord >> 30);
//
//	//P BIT2
//	aDWord = (*((unsigned int *)m_Packet)) & 0x20000000l;
//	m_Padding = (bool)(aDWord >> 29);
//
//	//X BIT3
//	aDWord = (*((unsigned int *)m_Packet)) & 0x10000000l;
//	m_HasExtention = (unsigned char)(aDWord >> 28)
//
//	//CC BIT(4-7)
//	aDWord = (*((unsigned int *)m_Packet)) & 0xf000000l;
//	m_NumCsrcs = (unsigned char)(aDWord >> 24);
//
//	//M BIT8
//	aDWord = (*((unsigned int *)m_Packet)) & 0x800000l;
//	m_HasMarker = (bool)(aDWord >> 23);
//
//	//PT BIT(9-15)
//	aDWord = (*((unsigned int *)m_Packet)) & 0xfe0000l;
//	m_PayloadType = (unsigned char)(aDWord >> 17);
//
//	//Sequence Number(BIT16-31)
//	aDWord = (*((unsigned int *)m_Packet)) & 0xffffl;
//	m_SeqNum = (unsigned short)aDWord;
//
//	//TIMESTAMP (BIT 32-63)
//	aDWord = *((unsigned int *)(m_Packet+4));
//	m_Timestamp = aDWord;
//
//	//SSRC
//	aDWord = *((unsigned int *)(m_Packet+8));
//	m_Ssrc = aDWord;
//
//	//CSRC
//	m_Csrc = ((unsigned int *)(m_Packet+18));
//	
//	unsigned char *p_Extension = m_Packet + 8 + 4*m_NumCsrcs;
//	//Ext head: Profile BIT(0-15)
//	aDWord = (*((unsigned int *)(p_Extension))) & 0xffff0000l;
//	m_ExtId = (unsigned short)(aDWord >> 16);
//
//	//Ext head: length BIT(16-31)
//	aDWord = (*((unsigned int *)(p_Extension))) & 0xffffl;
//	m_ExtLen = (unsigned short)aDWord;
//
//	//Ext head: header ext
//	m_Extension = p_Extension+4;
//
//	//Payload
//	m_Payload = m_Extension + m_ExtLen;
//	m_PayloadLen = m_PacketLen - m_ExtLen - m_NumCsrcs*4 - 16;
//}

unsigned int RtpPacket::GetVersion()
{
	unsigned int aDWord = *((unsigned int *)m_Packet);
	return (aDWord >> 30);
}

void RtpPacket::SetVersion(unsigned int v)
{
	if (m_IsBuffered)
	{
		DBGPRINT("Info--RtpPacket::SetVersion(%d)\n", v);
		unsigned char v8 = ((unsigned char)v & 3) << 6;
		*m_Packet = (*m_Packet) | v8;
		DBGPRINT("Info--Get out of RtpPacket::SetVersion()\n");
		return ;
	}
	DBGPRINT("Error--RtpPacket::SetVersion():Packet has not initialized\n");
}

unsigned int RtpPacket::GetPadding()
{
	unsigned int aDWord = *((unsigned int *)m_Packet);
	return (aDWord & 0x20000000l) >> 29;
}

void RtpPacket::SetPadding(unsigned int p)
{
	if (m_IsBuffered)
	{
		DBGPRINT("Info--RtpPacket::SetPadding(%d)\n", p);
		unsigned char v8 = ((unsigned char)p & 1) << 5;
		*m_Packet = (*m_Packet) | v8;
		DBGPRINT("Info--Get out of RtpPacket::SetPadding()\n");
		return ;
	}
	DBGPRINT("Error--RtpPacket::SetPadding():Packet has not initialized\n");
}

unsigned int RtpPacket::GetX()
{
	unsigned int aDWord = *((unsigned int *)m_Packet);
	return (aDWord & 0x10000000l) >> 28;
}

void RtpPacket::SetX(unsigned int x)
{
	if (m_IsBuffered)
	{
		DBGPRINT("Info--RtpPacket::SetX(%d)\n", x);
		unsigned char v8 = ((unsigned char)x & 1) << 4;
		*m_Packet = (*m_Packet) | v8;
		DBGPRINT("Info--Get out of RtpPacket::Setx()\n");
		return ;
	}
	DBGPRINT("Error--RtpPacket::SetX():Packet has not initialized\n");	
}

unsigned int RtpPacket::GetCC()
{
	unsigned int aDWord = *((unsigned int *)m_Packet);
	return (aDWord & 0xF000000l) >> 24;
}

void RtpPacket::SetCC(unsigned int cc)
{
	if (m_IsBuffered)
	{
		DBGPRINT("Info--RtpPacket::SetCC(%d)\n", cc);
		unsigned char v8 = ((unsigned char)cc & 0xf);
		*m_Packet = ((*m_Packet) | v8);
		DBGPRINT("Info--Get out of RtpPacket::SetCC()\n");
		return ;
	}
	DBGPRINT("Error--RtpPacket::SetCC():Packet has not initialized\n");
}

unsigned int RtpPacket::GetM()
{
	unsigned int aDWord = *((unsigned int *)(m_Packet+1));
	return (aDWord & 0x80000000l) >> 31;
}

void RtpPacket::SetM(unsigned int m)
{
	if (m_IsBuffered)
	{
		DBGPRINT("Info--RtpPacket::SetM(%d)\n", m);
		unsigned char v8 = ((unsigned char)m & 1) << 7;
		*(m_Packet+1) = (*(m_Packet+1)) | v8;
		DBGPRINT("Info--Get out of RtpPacket::SetM()\n");
		return ;
	}
	DBGPRINT("Error--RtpPacket::SetM():Packet has not initialized\n");
}

unsigned int RtpPacket::GetPayloadType()
{
	unsigned int aDWord = *((unsigned int *)(m_Packet+1));
	return (aDWord & 0x7F000000l) >> 24;
}

void RtpPacket::SetPayloadType(unsigned int pt)
{
	if (m_IsBuffered)
	{
		DBGPRINT("Info--RtpPacket::SetPayloadType(%d)\n", pt);
		unsigned char v8 = ((unsigned char)pt & 0x7f);
		*(m_Packet+1) = (*(m_Packet+1)) | v8;
		DBGPRINT("Info--Get out of RtpPacket::SetPayloadType()\n");
		return ;
	}
	DBGPRINT("Error--RtpPacket::SetPayloadType():Packet has not initialized\n");
}

unsigned int RtpPacket::GetSeqNum()
{
	unsigned short aWord = *((unsigned short *)(m_Packet+2));
	return aWord;
}

void RtpPacket::SetSeqNum(unsigned int sn)
{
	if (m_IsBuffered)
	{
		DBGPRINT("Info--RtpPacket::SetSeqNum(%d)\n", sn);
		unsigned short v8 = ((unsigned short)sn);
		*((unsigned short *)(m_Packet+2)) = *((unsigned short *)(m_Packet+2)) | v8;
		DBGPRINT("Info--Get out of RtpPacket::SetSeqNum()\n");
		return ;
	}
	DBGPRINT("Error--RtpPacket::SetSeqNum():Packet has not initialized\n");
}

unsigned int RtpPacket::GetTimestamp()
{
	unsigned int aDWord = *((unsigned int *)(m_Packet+4));
	return (aDWord);
}

void RtpPacket::SetTimestamp(unsigned int t)
{
	if (m_IsBuffered)
	{
		DBGPRINT("Info--RtpPacket::SetTimestamp(%d)\n", t);
		*((unsigned short *)(m_Packet+4)) = t;
		DBGPRINT("Info--Get out of RtpPacket::SetTimestamp()\n");
		return ;
	}
	DBGPRINT("Error--RtpPacket::SetTimestamp():Packet has not initialized\n");
}

unsigned int RtpPacket::GetSsrc()
{
	unsigned int aDWord = *((unsigned int *)(m_Packet+8));
	return (aDWord);
}

void RtpPacket::SetSsrc(unsigned int ssrc)
{
	if (m_IsBuffered)
	{
		DBGPRINT("Info--RtpPacket::SetSsrc(%d)\n", ssrc);
		*((unsigned short *)(m_Packet+8)) = ssrc;
		DBGPRINT("Info--Get out of RtpPacket::SetSsrc()\n");
		return ;
	}
	DBGPRINT("Error--RtpPacket::SetSsrc():Packet has not initialized\n");
}

unsigned int* RtpPacket::GetCsrc(unsigned int n)
{
	if (n < GetCC())
	{
		DBGPRINT("Info--RtpPacket::GetCSrc()\n");
		return ((unsigned int *)m_Packet) + n + 3;
	}
	DBGPRINT("Error--RtpPacket::GetCscr():n is larger than cc.\n");
	return 0;
}

void RtpPacket::SetCsrc(unsigned int n, unsigned int csrc)
{
	if (n < GetCC())
	{
		DBGPRINT("Info--RtpPacket::SetCSrc(%d, %d), n, csrc\n");
		*((unsigned int *)m_Packet +n+3) = csrc;
	}
	DBGPRINT("Error--RtpPacket::GetCscr():n is larger than cc.\n");
}

unsigned int RtpPacket::GetExtId()
{
	unsigned int aDWord = *((unsigned int*)m_Packet + 3 + GetCC());
	return (aDWord >> 16);
}

unsigned int RtpPacket::GetExtLen()
{
	if (!GetX()) return 0;
	unsigned int aDWord = *((unsigned int*)m_Packet + 3 + GetCC());
	return (aDWord & 0xffffl);
}

unsigned char* RtpPacket::GetExtension()
{
	unsigned int* pDWord = (unsigned int*)m_Packet + 4 + GetCC();
	return ((unsigned char*)pDWord); 
}

inline unsigned char* RtpPacket::GetPayload()
{
	return (GetExtension() + GetExtLen());
}

inline unsigned int RtpPacket::GetPayLoadLen()
{
	return (GetPacketLen() - GetExtLen() - GetCC()*4 - 12 - GetX()*4);
}
